/*******************************************************************************

	UBEC (Uniband Electronic Corp.)
	

	Project : UZ2400 Simple RF API

	File : simpleRF.c
	
	Description : Simple Rf Control Function
	
	Platform: U-Zig Power Module with IAR 8051 C compiler
	
	Reference: 

		Silicon Laboratories: C8051F124
		UBEC: UZ2400
		
	Note : 	


	Uniband Electronic Corporation
	3F-3, No. 192 Dongguang Rd., Hsinchu, 300 Taiwan
	Tel : 886-3-5729898, Fax : 886-3-5718599
	http: //www.ubec.com.tw


		Copyright (C) 2005 Uniband Electronic Corporation, All rights reserved
					
********************************************************************************/

#include "contiki.h"
#include "dev/uz2400_srf.h"

extern UINT8 SecKeyPool[16];

void uz2400_wakeup(){
  unsigned char m;

  uz2400_wakeup_pin_1;
  
  for(m=0;m<10;m++);
  
  uz2400_wakeup_pin_0;
}

void init_rf_pin(){
  uz2400_deselect();
  enable_uz2400_cs_output;
  uz2400_reset_pin_1;
  enable_uz2400_reset_output;
  
  P1DIR&=~0x1;
  P1IES|=0x1;
  P1IFG&=~0x1;  
  
  P1IE|=0x1;  
  
  uz2400_wakeup_pin_0;
  P4DIR|=(1<<5);
  uz2400_wakeup();
}

void wait_uz2400(){
  //UINT8 i=0;
  //for(i=100;i>0;i--); // modified to 1
}

/**************************************************************
	Function Name: UzInit()
	Description: Initial UZ2400
	Parameters: None
	Return Value: None
**************************************************************/

void UzInit(){
  UINT8 i;
  char test;
   
  uz2400_reset_pin_0;
  for(i=0;i<255;i++){}
  uz2400_reset_pin_1;
  for(i=0;i<255;i++){}
  
  do{
    spi_lw(TX_N_BASE,0x55);
  }while(spi_lr(TX_N_BASE)!=0x55);
  
  do{
    spi_lw(TX_N_BASE,0xAA);
  }while(spi_lr(TX_N_BASE)!=0xAA);
  
  //flush the RX fifo 
  spi_sw(RXFLUSH,0x01);

  //Set CCA mode to ED
  spi_sw(BBREG2, 0x80);

  //Apend RSSI value in Rx packets, Tx filter control, 20MHz clock recovery time control
  //spi_sw(BBREG6, 0xd0);
  spi_sw(BBREG6, 0x40);    // Append RSSI value in Rx packets
  
  //ED threshold for CCA
  spi_sw(RSSITHCCA, 0x60);
  
  //Errata Issue
  spi_sw(FFOEN, 0x98);

  spi_sw(TXPEMISP, 0x95);

  //20Mhz clock recovery time
  spi_sw(SLPACK, 0x5f);  
  
  //RF optimized control
  
  spi_lw(RFCTRL1, 0x01);    // UZ2400 Discrepancy Notes 002, rev. 1.1: 1. Optimal tuning option for RF performance
  
  spi_lw(RFCTRL2, 0x80); //RF-PLL Control
  
  spi_lw(RFCTRL6, 0x90);    //RF optimized control

  spi_lw(RFCTRL7, 0x80); //Sleep clock selection, [6:7] = 10 : use internal ring oscillator
  
  spi_lw(RFCTRL8, 0x10); // RF VCO control

  //Sleep clock frequency control
  spi_lw(SCLKDIV, 0x01);
  spi_sw(INTMSK, 0xF7);
     
  do{
      test = spi_lr(RFSTATE);
  }while((test&0xA0) != 0xA0);

  //Reset RF state machine
  spi_sw(RFCTL, 0x04);
  spi_sw(RFCTL, 0x00);
	
}

/**************************************************************
	Function Name: UzEnablePA()
	Description: Enable Power Amplifier (UP2202)
	Parameters: None
	Return Value: None
**************************************************************/

/*
For U-Power 500

Long register0x203=0x00
Long register0x22F=0x0F

//RFCTRL3     		0x203
//TESTMODE 		0x22f 

For U-Power 1000

Long register0x203=0x04
Long register0x22F=0x0F

*/


void UzEnablePA(){
  
  spi_lw(TESTMODE,  spi_lr(TESTMODE) | 0x07);
  UzSetTxPower(0);        // UZ2400 TX power = -10 dBm, for better EVM on UP2202
}


/**************************************************************
	Function Name:  UzSetTxPower()
	Description: Set Power Level
	Parameters: dB -> Power Level
	Return Value: None
	Note: If dB > 0 ,will reduce power level
**************************************************************/
void UzSetTxPower(INT8 dB)    // dB Range: 0 ~ -40
{
#if 1
    UINT16 Value;

    if(dB < 0)
        dB = -dB;
    Value = dB * 100 + 62;
    if((INT16)Value >= 4000)
        Value = 3999;
    else if((INT16)Value < 0)
        Value = 0;

    spi_lw(RFCTRL3, (UINT8)(((Value / 1000) * 8) | ((Value % 1000) / 125)) * 8);
#else
    UINT8 Value = 0x00;
    INT8 Operator = 0x00;

    TRACE_puts("UzSetTxPower\r\n");

    if(dB > 40 || dB < 0)
        return;

    if(dB == 0){ //Maximum Tx Power
        Value = 0;
    }else{
        if((Operator = dB - 40) >=0){ //dB = 40
            Value |= 0xc0;
            spi_lw(RFCTRL3, Value); //Set Power
            Value &= 0x00;
            Value |=0x40;
        }else if((Operator = dB - 30) >=0){//30 <= dB < 40
            Value |= 0xc0;
        }else if((Operator = dB - 20) >=0){//20 <= dB < 30
            Value |= 0x80;
        }else if((Operator = dB - 10) >=0){//10 <= dB < 20
            Value |= 0x40;
        }else{                                            // 0 < dB < 10
            Operator = dB;
        }

        if(Operator != 0){
            if(Operator == 1){
                Value |= 0x08;
            }else if(Operator == 2 || Operator == 3){
                Value |= 0x10;
            }else if(Operator == 4){
                Value |= 0x18;
            }else if(Operator == 5){
                Value |= 0x20;
            }else if(Operator == 6){
                Value |= 0x28;
            }else if(Operator == 7){
                Value |= 0x30;
            }else{//Operator == 8 or 9
                Value |= 0x38;
            }
        }
    }

    spi_lw(RFCTRL3, Value);
#endif
}

/**************************************************************
	Function Name: UzSetChannel()
	Description: Set Channel
	Parameters: NewChannel -> Logical Channel you want modify, Value Range 11~26
	Return Value: None
**************************************************************/

void UzSetChannel(UINT8 NewChannel){ 

  if (NewChannel > 26 || NewChannel < 11) return; //Check Channel Range
  
  spi_lw(RFCTRL0, ((NewChannel - 11) << 4) + 0x02); //// Shift logic channel, Program Channel
  
  //Reset RF state machine
  spi_sw(RFCTL, 0x04);
  spi_sw(RFCTL, 0x00);

}

/**************************************************************
	Function Name: UzSetCca()
	Description: Setup CSMA/CA Mode and Threshold
	Parameters: CCAMode -> CSMA/CA mechanism, CS only, ED only or CS |ED hybrid
			     CS_TH -> Threshold for Carrier Sense Mode
			     ED_TH -> Threshold for Energy Detect Mode
	Return Value: None
**************************************************************/

#define CCA_ED_MODE 0x80
#define CCA_CS_MODE 0x40

void UzSetCca(UINT8 CCAMode, UINT8 CS_TH, UINT8 EDT_TH){
  UINT8 Value = 0x00;
  
  Value |= CCAMode;
  
  if(CCAMode != CCA_ED_MODE){ // Set Threshold for CS or Hybrid
    Value |= ((CS_TH & 0x0f) << 2);
  }
  
  if(CCAMode != CCA_CS_MODE){ // Set Threshold for ED or Hybrid
    spi_sw(RSSITHCCA, EDT_TH);
  }
  
  spi_sw(BBREG2, Value); //Program Channel
}

/**************************************************************
	Function Name: UzReadRSSI()
	Description: Read current RSSI value
	Parameters: None
	Return Value: RSSI Value
**************************************************************/

UINT8 UzReadRSSI(){
  spi_sw(BBREG6, spi_sr(BBREG6) | 0x80); // Issue RSSI Request
  
  while(!(spi_sr(BBREG6) & 0x1)); //Wait Value Ready
   
  return  spi_lr(RSSI);
}

/**************************************************************
	Function Name: UzSetMacAddress()
	Description: Set Mac Address
	Parameters: MacAddress -> 64bits Mac Address Pointer
	Return Value: None
	Note: Mac Address is used as the hardware filter of RX Normal Mode 
**************************************************************/

void UzSetMacAddress(UINT8 *MacAddress){
  UINT8 i;
  
  for (i=0; i<8; i++)
  spi_sw(EADR0+i, *(MacAddress+i)); //Set Value 
	
}

/**************************************************************
	Function Name: UzSetPanId()
	Description: Set Pan Id
	Parameters: PanId -> 16bits PAN identifier
	Return Value: None
	Note: Pan Id is used as the hardware filter of RX Normal Mode 
**************************************************************/

void UzSetPanId(UINT16 PanId){
  UINT8 i;
  
  for(i=0; i<2; i++)
    spi_sw(PANIDL+i, *(((UINT8 *)&PanId)+i)); //Set Value
}

/**************************************************************
	Function Name: UzSetNwkAddr()
	Description: Set Network(16bits) Address
	Parameters: NwkAddr -> 16bits short Address
	Return Value: None
**************************************************************/

void UzSetNwkAddr(UINT16 NwkAddr){
  UINT8 i;
  
  for(i=0; i<2; i++){
    spi_sw(SADRL+i, *(((UINT8 *)&NwkAddr)+i)); //Set Value
  }
}

/**************************************************************
	Function Name: UzSoftReset()
	Description: Reset UZ2400 by Software
	Parameters: None
	Return Value: None
**************************************************************/

void UzSoftReset(){
  //Reset Power management, Base band, Mac
  spi_sw(SOFTRST, 0x07);
}

/**************************************************************
	Function Name: UzRxPromiscouosMode()
	Description: Set Promiscouos Mode of Rx
	Parameters: None
	Return Value: None
**************************************************************/

void UzRxPromiscouosMode(){
  spi_sw(RXMCR, spi_sr(RXMCR) | 0x01); // Accept all packets with CRC OK
}

/**************************************************************
	Function Name: UzRxErrorMode()
	Description: Set Error Mode of Rx
	Parameters: None
	Return Value: None
**************************************************************/

void UzRxErrorMode(){
  spi_sw(RXMCR, spi_sr(RXMCR) | 0x03); // Accept all kinds of pkt(even CRC error)
} 

/**************************************************************
	Function Name: UzRxNormalMode()
	Description: Set Normal Mode of Rx
	Parameters: None
	Return Value: None
**************************************************************/

void UzRxNormalMode(){
  spi_sw(RXMCR, spi_sr(RXMCR) & ~0x03); // Accept packets with crossponding Pan Id , Mac Address or Network Addrss
}


/**************************************************************
	Function Name: UzEnabTurboMode()
	Description: Enable The Turbo Mode of UZ2400
	Parameters: None
	Return Value: None
**************************************************************/

void UzEnabTurboMode(){
  spi_sw(BBREG0, spi_sr(BBREG0) | 0x01);
  spi_sw(BBREG3, spi_sr(BBREG3) | 0x38);
  spi_sw(BBREG4, spi_sr(BBREG4) | 0x5C);
}


/**************************************************************
	Function Name: UzDisTurboMode()
	Description: Disable The Turbo Mode of UZ2400
	Parameters: None
	Return Value: None
**************************************************************/

void UzDisTurboMode(){
  spi_sw(BBREG0, spi_sr(BBREG0) & ~0x01);
  spi_sw(BBREG3, spi_sr(BBREG3) & ~0x38);
  spi_sw(BBREG4, spi_sr(BBREG4) & ~0x5C);
}

/**************************************************************
	Function Name: UzForceTxMode()
	Description: 
	Parameters: None
	Return Value: None
**************************************************************/

void UzForceTxMode(){
  spi_sw(RFCTL, spi_sr(RFCTL) | 0x02);
}


/**************************************************************
	Function Name: UzTx()
	Description: Send Raw Data
	Parameters: DataPtr -> Out Data Pointer
	                   Length -> Out data Length
	                   
	Return Value: SUCCESS -> Send Data Successful
	                     FAILURE -> Send Data Failure 
**************************************************************/

INTERRUPT_STS IntFlag = {0, 0, 0, 0, 0, 0, 0, 0}; // Interrupt Flag

UINT8 UzPrepare(UINT8 *DataPtr, UINT8 Length){
	
  UINT8 Value;	
  spi_lw(TX_N_LEN, Length); // Fill Data Length Into TXFIFO
  
  spi_fill_fifo(TX_N_BASE, DataPtr, Length); //Fill Data Into TXFIFO

  Value = spi_sr(TXNMTRIG);
  
  if(*(DataPtr) & 0x20){
    Value &= ~0x07; //Clear
    Value |= 0x05; //Set Ackreq(SREG0x1B[2]) if re-transmission is required
    
    UzRxFlush();
    
    //Set Wait Time
    //Timer = ((640 + 32*Length + 912)*3 + 2816); //(CCA + Tx*Length + AckWaitDuration)*MaxRetry + Backoff (us) , System Clock: 10MHz
  }else{
    Value &= ~0x07; //Clear
    Value |= 0x01;
    
    //Set Wait Time
    //Timer = ((640 + 32*Length + 912)*3); //(CCA + Tx*Length)*MaxRetry + Backoff (us) , System Clock: 10MHz
  }
  Value &= ~0x01;
  spi_sw(TXNMTRIG, Value);
  
}
UINT8 UzTransmit(UINT8 Length) {
	
  UINT8 Value, cnt;
  UINT32 Timer;
  
  cnt = 0;
  Value = spi_sr(TXNMTRIG);
  Value |= 0x01;
  
  spi_sw(TXNMTRIG, Value);
  while(!(spi_sr(ISRSTS) & 0x01));
  
RETRY_ENTRY:

  if(!(spi_sr(TXSR) & 0x01)) {// determine whether TX success
	return SUCCESS;
  } else {
	if(++cnt < 5) {
      int nop;
      for(nop = 100; nop > 0; nop--) asm("nop"); 
	  goto RETRY_ENTRY;
	} else 
	  return FAILURE;
  }
}

UINT8 UzTx(UINT8 *DataPtr, UINT8 Length){
  UINT8 Value, cnt;
  UINT32 Timer;
  
  cnt = 0;
  
  spi_lw(TX_N_LEN, Length); // Fill Data Length Into TXFIFO
  
  spi_fill_fifo(TX_N_BASE, DataPtr, Length); //Fill Data Into TXFIFO

  Value = spi_sr(TXNMTRIG);
  
  if(*(DataPtr) & 0x20){
    Value &= ~0x07; //Clear
    Value |= 0x05; //Set Ackreq(SREG0x1B[2]) if re-transmission is required
    
    UzRxFlush();
    
    //Set Wait Time
    //Timer = ((640 + 32*Length + 912)*3 + 2816); //(CCA + Tx*Length + AckWaitDuration)*MaxRetry + Backoff (us) , System Clock: 10MHz
  }else{
    Value &= ~0x07; //Clear
    Value |= 0x01;
    
    //Set Wait Time
    //Timer = ((640 + 32*Length + 912)*3); //(CCA + Tx*Length)*MaxRetry + Backoff (us) , System Clock: 10MHz
  }
  
  spi_sw(TXNMTRIG, Value);  //Set trigger bit(SREG0x1B[0]) to send packet This bit will be automatically cleared.

  while(!(spi_sr(ISRSTS) & 0x01));
  
RETRY_ENTRY:

  if(!(spi_sr(TXSR) & 0x01)) {// determine whether TX success
	return SUCCESS;
  } else {
	if(++cnt < 5) {
      int nop;
      for(nop = 100; nop > 0; nop--) asm("nop"); 
	  goto RETRY_ENTRY;
	} else 
	  return FAILURE;
  }
}

/**************************************************************
	Function Name:  UzRx()
	Description: Receive Data fron RXFIFO
	Parameters: RecvBuff -> Data buff that put received data
	Return Value: reveived data length
**************************************************************/

UINT8 UzRx(UINT8 *RecvBuff){ 
  UINT8 Length;
  
    spi_rd_rx_fifo(RecvBuff, &Length); //Receive Data from RxFIFO
    
    
    UzRxFlush();
    return Length;
  UzRxFlush();
  return 0;
}

/**************************************************************
	Function Name: UzRxOnlyBeacon()
	Description: Let Rx Receive Only IEEE 802.15.4 Beacon Frame
	Parameters: None
	Return Value: None
**************************************************************/
/*
void UzRxOnlyBeacon(){
  spi_sw(RXFLUSH, (spi_sr(RXFLUSH) & ~0x0e) | 0x02);
}*/

/**************************************************************
	Function Name: UzRxOnlyCommand()
	Description: Let Rx Receive Only IEEE 802.15.4 Command Frame
	Parameters: None
	Return Value: None
**************************************************************/
/*
void UzRxOnlyCommand(){
  spi_sw(RXFLUSH, (spi_sr(RXFLUSH) & ~0x0e) | 0x08);
}*/


/**************************************************************
	Function Name: UzRxOnlyData()
	Description: Let Rx Receive Only IEEE 802.15.4 Data Frame
	Parameters: None
	Return Value: None
**************************************************************/
/*
void UzRxOnlyData(){
  spi_sw(RXFLUSH, (spi_sr(RXFLUSH) & ~0x0e) | 0x04);
}*/

/**************************************************************
	Function Name: UzRxAllFrame()
	Description: Let Rx Receive all IEEE 802.15.4 Frame
	Parameters: None
	Return Value: None
**************************************************************/
/*
void UzRxAllFrame(){
  spi_sw(RXFLUSH, spi_sr(RXFLUSH) & ~0x0e);
}*/

/**************************************************************
	Function Name: UzRxFlush()
	Description: Drop data in RXFIFO 
	Parameters: None
	Return Value: None
**************************************************************/

void UzRxFlush(){
  spi_sw(RXFLUSH, spi_sr(RXFLUSH) | 0x01);// Trigger drop data
}

/**************************************************************
Diego 2009/07/01
        Function Name: UzSwWakeup()
        Description: Force UZ2400 to be awaken
        Parameters: None
        Return Value: None
**************************************************************/
void UzSwWakeup(void)
{
    //EnableSPI();

    spi_sw(TXBCNINTL, spi_sr(TXBCNINTL) | ExtWakeupAlert | ExtWakeupMode);
    clock_delay(706); // 2ms delay
    spi_sw(TXBCNINTL, spi_sr(TXBCNINTL) & (~ExtWakeupAlert));

    spi_sw(RFCTL, spi_sr(RFCTL) | RFRESET);
    spi_sw(RFCTL, spi_sr(RFCTL) & (~RFRESET));
    clock_delay(706); // 2ms delay
}

/**************************************************************
Diego 2009/07/01
        Function Name: UzSwSleep()
        Description: Force UZ2400 into Sleep Mode with software-wakeup state
        Parameters: None
        Return Value: None
**************************************************************/
void UzSwSleep(void)
{
    //while (IntStatus.Wakeup)
    //{
    //    IntStatus.Wakeup=0;
    //} 

    spi_sw(TXBCNINTL, spi_sr(TXBCNINTL) | ExtWakeupMode);
    UzSleep();

    //DisableSPI();
}

/**************************************************************
	Function Name: UzSleep()
	Description: Force UZ2400 into Sleep Mode
	Parameters: None
	Return Value: None
**************************************************************/

void UzSleep(){
  spi_sw(SLPACK ,spi_sr(SLPACK) | 0x80);
}

/**************************************************************
	Function Name: UzTimedSleep()
	Description: Periodic Sleep Mode of UZ2400
	Parameters: MS -> Sleep Time
	Return Value: None
**************************************************************/

void UzTimedSleep(UINT8 MS){  // Range 0~2000 MS, use in un-sloted mode
  INT16 Main, Remain;
  div_t Temp;
  
  Temp = div(1000000*MS, 30517);  //If sleep clock = 32.768KHz
  Main = Temp.quot;
  
  Temp = div(1000*Temp.rem, 50); // System clock = 20MHz
  Remain = Temp.quot;
  
  //Set Main Counter
  spi_lw(TXMAINCNTH0, 0);
  
  spi_lw(TXMAINCNTM, (Main & 0xff00) >> 8);
  
  spi_lw(TXMAINCNTL, (Main & 0x00ff));
  
  //Set Re-main Counter
  spi_lw(TXREMCNTH, (Remain & 0xff00) >> 8);
  
  spi_lw(TXREMCNTL, (Remain & 0x00ff));
  
  //WakeCnt
  spi_sw(SLPACK ,spi_sr(SLPACK) |0x41);
  
  spi_sw(RFCTL, spi_sr(RFCTL) & ~0x18);
  
  //Trigger sleep
  spi_lw(TXMAINCNTH1, spi_lr(TXMAINCNTH1) | 0x80);

}

/**************************************************************
	Function Name: UzRegWakeUp()
	Description: Register Wake Up Mode, wake Up UZ2400
	Parameters: None
	Return Value: None
**************************************************************/

void UzRegWakeUp(){
  UINT8 Value;
  
  //Disable ext. wake up (im. wakeup mode), Register wake up
  Value = spi_sr(TXBCNINTL);
  Value &= ~0x80;
  
  Value |= 0x40;
  spi_sw(TXBCNINTL, Value); 
  
  //Flag be released by software
  Value &= ~0x40;
  spi_sw(TXBCNINTL, Value);
}

/**************************************************************
	Function Name: UzPowWakeUp()
	Description: Power Management Wake Up Mode, wake Up UZ2400
	Parameters: None
	Return Value: None
**************************************************************/

void UzPowWakeUp(){
  
  //Disable ext. wake up
  spi_sw(TXBCNINTL, spi_sr(TXBCNINTL) & ~0x80);
  
  //Reset power management
  spi_sw(SOFTRST, spi_sr(SOFTRST) | 0x04);
}

/**************************************************************
	Function Name: UzEnabExtWakeUp()
	Description: Enable External Wake Up
	Parameters: None
	Return Value: None
**************************************************************/

void UzEnabExtWakeUp(){
  
  spi_sw(TXBCNINTL, spi_sr(TXBCNINTL) | 0x80);
  
  spi_sw(RXFLUSH, spi_sr(RXFLUSH) | 0x60);
}

/**************************************************************
	Function Name: UzEnabBatteryLifeEx()
	Description: Set IEEE 802.15.4 Battey Life Extension
	Parameters: None
	Return Value: None
**************************************************************/

void UzEnabBatteryLifeEx(){
  spi_sw(TXMCR, spi_sr(TXMCR) | 0x40);
}


/**************************************************************
	Function Name: UzDisBatteryLifeEx()
	Description: Set IEEE 802.15.4 Battey Life Extension
	Parameters: None
	Return Value: None
**************************************************************/

void UzDisBatteryLifeEx(){
  spi_sw(TXMCR, spi_sr(TXMCR) & ~0x40);
}

/**************************************************************
	Function Name:  UzSecureTx()
	Description: Transmit Secure Data
	Parameters: SecMode -> Encryption Mode
	                   *SecKey -> Security Key, defined by user
	                   *DataPtr -> Data Pointer
	                   Length -> Data Length
	                   HeaderLength -> Length of Data Header	                
	Return Value: SUCCESS -> Send Data Successful
	                     FAILURE -> Send Data Failure 
**************************************************************/

UINT8 UzSecureTx(UINT8 SecMode, UINT8 *SecKey, UINT8 *DataPtr, UINT8 Length, UINT8 HeaderLength){
  UINT8 Value;
  UINT32 Timer; 
  
  //Fill TXFIFO
  spi_lw(TX_N_HDR, HeaderLength); //Header Length
  spi_lw(TX_N_LEN, Length); //Data Length
  spi_fill_fifo(TX_N_BASE, DataPtr, Length); //Data
  
  //Fill Security key
  spi_fill_fifo(KEY_TX_N, SecKey, 16);
  
  //Fill in cipher mode
  spi_sw(SECCR0, (spi_sr(SECCR0) & ~0x07) | SecMode);
  
  Value = spi_sr(TXNMTRIG);
  
  if(*(DataPtr) & 0x20){
    Value |= 0x05; //Set Ackreq(SREG0x1B[2]) if re-transmission is required
    
    //Set Wait Time
    Timer = ((640 + 32*Length + 912)*3 + 2816)*2; //(CCA + Tx*Length + AckWaitDuration)*MaxRetry + Backoff (us) , System Clock: 20MHz
  }else{
    Value &= ~0x07; //Clear
    Value |= 0x01;
    
    //Set Wait Time
    Timer = ((640 + 32*Length + 912)*3)*2; //(CCA + Tx*Length)*MaxRetry + Backoff (us) , System Clock: 20MHz
    }
  
  spi_sw(TXNMTRIG, Value); //Trigger Tx start with security
  
  while(Timer > 0){
    if(IntFlag.TxN == 1){

      DisInt();
      IntFlag.TxN = 0;
      EnabInt();
      
      if(!(spi_sr(TXSR) & 0x01)){ //Check TXFIFO release state
        return SUCCESS;
      }else{
        break;
      }			
    }
    
    Timer -= 1;
  }
  
  return FAILURE;
}

/**************************************************************
	Function Name: UzSecureRx()
	Description: Receive Secure Data
	Parameters: SecMode -> Decryption Mode
	                   *SecKey -> Security Key, defined by user
	                   *InBuff -> Data Buffer Pointer
	Return Value: Length -> Received Data Length
**************************************************************/

UINT8 UzSecureRx(UINT8 SecMode, UINT8 *SecKey, UINT8 *InBuff){
  UINT8 Length;
  
  if(IntFlag.Sec == 1){
  IntFlag.Sec = 0;
  
  spi_fill_fifo(KEY_RX_N, SecKey, 16);//Fill Secure key into FIFO
  
  spi_sw(SECCR0, (spi_sr(SECCR0) & ~0x38) | SecMode); //Fill cipher mode
  
  //Security start
  spi_sw(SECCR0, spi_sr(SECCR0) | 0x40); // Trigger Security Process 
  
  //Wait Interrupt
  while(1){
    if(IntFlag.Rx == 1){
      spi_rd_rx_fifo(InBuff, &Length); //Fetch Data from RXFIFO
      IntFlag.Rx =0; //Reset Interrupt Flag
      return Length;
      }
    }		
  }
  
  return 0;
}



